﻿using System;
using System.Collections.Generic;
using LitJson;
using UnityEngine;
using System.Collections;
using System.Reflection;
using HopeUtils;

#if UNITY_EDITOR
using UnityEditor;
#endif

/// <summary>
/// <para>教学节点中使用的Attribute（特性），目前仅支持Field（成员变量）和Property（属性）</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonAttribute : Attribute
{
	/// <summary>
	/// <para>保留关键字数组</para>
	/// </summary>
	public static string[] ReservedWords = new string[] { ReservedWordClass };

	/// <summary>
	/// <para>保留关键字class，用作类名</para>
	/// </summary>
	public static string ReservedWordClass = "class";

	/// <summary>
	/// <para>函数标签，后跟函数名，用冒号(;)分隔</para>
	/// </summary>
	public static string FunctionTag = "func";

	/// <summary>
	/// <para>json的键名</para>
	/// </summary>
	public string _key { get; private set; }

	/// <summary>
	/// <para>教学编辑器中显示的标签名</para>
	/// </summary>
	public string _label { get; private set; }

	/// <summary>
	/// <para>父成员变量的json键名</para>
	/// <para>父成员变量必须是bool，当其为false时，教学编辑器中将不显示其所有的子成员变量</para>
	/// </summary>
	public string _parentKey { get; private set; }

	/// <summary>
	/// <para>教学编辑器中数组或List显示的子标签名，支持多个标签，用逗号(,)分隔，或传入返回字符串数组的一个函数名，用FunctionTag标记</para>
	/// <para>例1: "成功标签, 失败标签"</para>
	/// <para>例2: "func: GetTagLabels"</para>
	/// </summary>
	public string _sublabels { get; private set; }

    /// <summary>
	/// <para>父成员变量的需要的值</para>
	/// <para>例1: 当父成员是枚举的时候，填入需要的枚举名称</para>
	/// </summary>
	public string _parentValue { get; private set; }

    /// <summary>
    /// <para>构造函数</para>
    /// </summary>
    public JsonAttribute(string key, string label = "", string parentKey = "", string sublabels = "", string parentValue = "")
	{
		_key = key;
		_label = label;
		_parentKey = parentKey;
		_sublabels = sublabels;
        _parentValue = parentValue;

    }

	/// <summary>
	/// <para>解析_labelInfo获得所有的label</para>
	/// </summary>
	public string[] GetSublabels(object inst)
	{
		if (_sublabels.Length == 0)
			return new string[]{ };
		
		var eles = _sublabels.Split(new char[]{ ':' }, StringSplitOptions.RemoveEmptyEntries);
		if (eles.Length == 2) {
			for (int i = 0; i < eles.Length; ++i)
				eles[i] = eles[i].Trim();
			if (eles[0] == FunctionTag && inst != null) {
				var method = inst.GetType().GetMethod(eles[1]);
				if (method != null) {
					if (method.ReturnType == typeof(string[])) {
						return (string[])method.Invoke(inst, new object[]{ });
					} else {
						Debug.LogError("JsonAttribute GetLabels error: method return type not fit: " + method.ReturnType.ToString());
					}
				} else {
					Debug.LogError("JsonAttribute GetLabels error: cannot find method: " + eles[1]);
				}
			}
		}

		var labels = _sublabels.Split(new char[]{ ',' }, StringSplitOptions.RemoveEmptyEntries);
		for (int i = 0; i < labels.Length; ++i)
			labels[i] = labels[i].Trim();
		return labels;
	}
}

/// <summary>
/// <para>教学脚本所支持的类的Attribute（特性）</para>
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class JsonClassAttribute : Attribute
{
}

/// <summary>
/// <para>教学脚本编辑器特有的成员变量的Attribute（特性），用于成员变量在编辑器中显示类型和存储类型不一样的情况。</para>
/// <para>例如：在教学脚本中存有一个字符串类型的变量，但在编辑器中想用下拉菜单来选择而不是填写一个字符串，那么就可以使用此特性</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonEditorAttribute : Attribute
{
	/// <summary>
	/// <para>编辑器特殊成员处理对象</para>
	/// </summary>
	public IEditorSpecialMember _specialMember = null;

	/// <summary>
	/// <para>相关的成员变量的键</para>
	/// </summary>
	public string _relativeKey { get; private set; }

	/// <summary>
	/// <para>构造函数</para>
	/// </summary>
	public JsonEditorAttribute(Type type, string relativeKey)
	{
		_specialMember = Activator.CreateInstance(type) as IEditorSpecialMember;
		_relativeKey = relativeKey;
	}
}

/// <summary>
/// <para>教学脚本编辑器特有的成员变量的Attribute（特性），用于成员变量在编辑器中显示类型和存储类型不一样的时候，给EditorAttribute传参数。</para>
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class JsonEditorparametersAttribute : Attribute
{
    public HashSet<string> parmsSet = new HashSet<string>();
    /// <summary>
    /// <para>构造函数</para>
    /// </summary>
    public JsonEditorparametersAttribute(params string[] list)
    {
        foreach (var item in list)
        {
            parmsSet.Add(item);
        }
    }
}


/// <summary>
/// <para>教学脚本所支持的类的Attribute（特性）</para>
/// </summary>
public static class TutorialJsonUtils
{
	#region reflection utilities

	/// <summary>
	/// <para>反射标志，目前支持非静态变量和属性</para>
	/// </summary>
	public static BindingFlags _bindingFlag = BindingFlags.Instance
	                                          | BindingFlags.Public
	                                          | BindingFlags.NonPublic;

	/// <summary>
	/// <para>通过反射获取成员的值</para>
	/// </summary>
	public static object GetValueOfMember(object inst, MemberInfo member)
	{
		if (member != null) {
			if (member is FieldInfo) {
				return ((FieldInfo)member).GetValue(inst);
			} else if (member is PropertyInfo) {
				return ((PropertyInfo)member).GetValue(inst, null);
			}
		}

		return null;
	}

	/// <summary>
	/// <para>通过反射设置成员的值</para>
	/// </summary>
	public static void SetValueOfMember(ref object inst, MemberInfo member, object val)
	{
		if (member != null) {
			if (member is FieldInfo) {
				((FieldInfo)member).SetValue(inst, val);
			} else if (member is PropertyInfo) {
				((PropertyInfo)member).SetValue(inst, val, null);
			}
		}
	}

	/// <summary>
	/// <para>通过反射获取成员的类型</para>
	/// </summary>
	public static Type GetTypeOfMember(MemberInfo member)
	{
		if (member != null) {
			if (member is FieldInfo) {
				return ((FieldInfo)member).FieldType;
			} else if (member is PropertyInfo) {
				return ((PropertyInfo)member).PropertyType;
			}
		}
		return default(Type);
	}

	/// <summary>
	/// <para>获取相应的属性键所对应的成员反射对象</para>
	/// </summary>
	public static MemberInfo GetJsonAttributeMemberByKey(Type type, string key)
	{
		foreach (var field in type.GetFields (_bindingFlag)) {
			var objs = field.GetCustomAttributes(typeof(JsonAttribute), true);
			if (objs != null && objs.Length > 0) {
				var customAttr = ((JsonAttribute)objs[0]);
				if (customAttr._key == key) {
					return field;
				}
			}
		}
		foreach (var prop in type.GetProperties (_bindingFlag)) {
			var objs = prop.GetCustomAttributes(typeof(JsonAttribute), true);
			if (objs != null && objs.Length > 0) {
				var customAttr = ((JsonAttribute)objs[0]);
				if (customAttr._key == key) {
					return prop;
				}
			}
		}

		return null;
	}

	#endregion

	#region get json from instance

	#if UNITY_EDITOR
    public struct ParentCache
    {
        MemberInfo memberinfo;

    }

	static Dictionary<MemberInfo, Tuple<MemberInfo, bool>> _parentMemberCache = new Dictionary<MemberInfo, Tuple<MemberInfo, bool>>();

	/// <summary>
	/// <para>通过反射获取父成员变量，没有则返回null</para>
	/// </summary>
	static MemberInfo GetParentMember(Type type, MemberInfo member, ref bool negative, out string parentValue)
	{
        parentValue = "";
        negative = false;
		if (member != null) {
			//if (_parentMemberCache.ContainsKey(member)) {
			//	negative = _parentMemberCache[member]._item2;
			//	return _parentMemberCache[member]._item1;
			//} else {
				MemberInfo parentMember = null;
				var objs = member.GetCustomAttributes(typeof(JsonAttribute), true);
				if (objs != null && objs.Length > 0) {
					var customAttr = ((JsonAttribute)objs[0]);
					var parentKey = customAttr._parentKey;
                    parentValue = customAttr._parentValue;
                    if (!string.IsNullOrEmpty(parentKey)) {
						if (parentKey.StartsWith("!")) {
							parentKey = parentKey.Substring(1).Trim();
							negative = true;
						}
						parentMember = GetJsonAttributeMemberByKey(type, parentKey);
					}
				}
				//_parentMemberCache.Add(member, new Tuple<MemberInfo, bool>(parentMember, negative));
				return parentMember;
			//}
		}
		return null;
	}

	/// <summary>
	/// <para>递归判断某成员变量是否处于激活状态。</para>
	/// <para>父成员变量处于未激活状态时，所有的子成员变量都处于未激活状态</para>
	/// </summary>
	public static bool IsMemberActive<T>(object inst, MemberInfo member) where T : Attribute
	{
		if (member == null)
			return true;

		if (typeof(T) == typeof(JsonAttribute)) {
            string parentValue;
			bool negative = false;
			var parentMember = GetParentMember(inst.GetType(), member, ref negative, out parentValue);
			var checkMember = parentMember;
			var parentEditorMember = GetEditorAttributeMember(parentMember, inst);
			if (parentEditorMember != null) {
				checkMember = parentEditorMember;
			}
			var val = GetValueOfMember(inst, checkMember);
            if(val == null)
            {
                return true;
            }
            if (val is Boolean)
            {
                return (negative == !(bool)val) && IsMemberActive<T>(inst, parentMember);
            }
            else if (val.GetType().IsEnum)
            {
                return (int)val == (int)Enum.Parse(val.GetType(), parentValue);
            }else {
				return true;
			}
		} else
			return true;
	}

	/// <summary>
	/// <para>json读写时的小数精度，设置为3位</para>
	/// </summary>
	static readonly int DecimalPrecision = 3;

	/// <summary>
	/// <para>根据小数精度四舍五入</para>
	/// </summary>
	static double GetRoundedFloat(double val)
	{
		return Math.Round(val, DecimalPrecision);
	}

	/// <summary>
	/// <para>往Json对象中写入键和值</para>
	/// </summary>
	public static void SetJson(JsonData data, string key, object val)
	{
		if (val is JsonData)
			data[key] = (JsonData)val;
		else
			data[key] = new JsonData(val);
	}

	/// <summary>
	/// <para>缓存成员反射信息以提升编辑器运行效率</para>
	/// </summary>
	static Dictionary<Type, Dictionary<Type, List<MemberInfo>>> _memberInfoCache = new Dictionary<Type, Dictionary<Type, List<MemberInfo>>>();

	/// <summary>
	/// <para>通过反射获取带有某个Attribute类型T的所有成员变量和属性</para>
	/// </summary>
	static List<MemberInfo> GetAttributeMembers<T>(object inst) where T : Attribute
	{
		var type = inst.GetType();
		List<MemberInfo> allMembers = null;
		if (_memberInfoCache.ContainsKey(type)) {
			if (_memberInfoCache[type].ContainsKey(typeof(T))) {
				allMembers = _memberInfoCache[type][typeof(T)];
			}
		}
		if (allMembers == null) {
			allMembers = new List<MemberInfo>();
			foreach (var field in type.GetFields (_bindingFlag)) {
				var objs = field.GetCustomAttributes(typeof(T), true);
				if (objs != null && objs.Length > 0) {
					allMembers.Add(field);
				}
			}
			foreach (var prop in type.GetProperties (_bindingFlag)) {
				var objs = prop.GetCustomAttributes(typeof(T), true);
				if (objs != null && objs.Length > 0) {
					allMembers.Add(prop);
				}
			}
			if (!_memberInfoCache.ContainsKey(type)) {
				var dict = new Dictionary<Type, List<MemberInfo>>();
				dict.Add(typeof(T), allMembers);
				_memberInfoCache.Add(type, dict);
			} else {
				_memberInfoCache[type].Add(typeof(T), allMembers);
			}
		}

		var members = new List<MemberInfo>();
		for (int i = 0; i < allMembers.Count; ++i) {
			if (IsMemberActive<T>(inst, allMembers[i]))
				members.Add(allMembers[i]);
		}

		return members;
	}

	/// <summary>
	/// <para>将某个对象inst序列化为json数据，递归获取</para>
	/// </summary>
	public static object GetJsonData(object inst)
	{
		if (inst == null) {
			JsonData data = new JsonData(null);
			return data;
		} else if (inst is IList) {
			var list = (IList)inst;
			if (list.Count > 0) {
				var jdArray = new JsonData();
				foreach (var item in list) {
					jdArray.Add(GetJsonData(item));
				}
				return jdArray;
			} else {
				return JsonMapper.ToObject("[]");
			}
		} else if (inst is IDictionary) {
			var dict = (IDictionary)inst;
			if (dict.Count > 0) {
				var jdDict = new JsonData();
				foreach (var k in dict.Keys) {
					var jdKey = GetJsonData(k);
					string key = k.ToString();
					if (jdKey is JsonData)
						key = ((JsonData)jdKey).ToJson();
					var val = dict[k];
					var jdVal = GetJsonData(val);
					SetJson(jdDict, key, jdVal);
				}
				return jdDict;
			} else {
				return JsonMapper.ToObject("{}");
			}
		} else {
			if (inst is Boolean || inst is Int32 || inst is Int64 || inst is String) {
				return inst;
			} else if (inst is Double) {
				return GetRoundedFloat((double)inst);
			} else if (inst is Single) {
				return GetRoundedFloat((double)(float)inst);
			} else if (inst is Enum) {
				return (int)inst;
			} else if (inst is Rect) {
				var rect = (Rect)inst;
				JsonData rectData = new JsonData();
				rectData["x"] = GetRoundedFloat(rect.x);
				rectData["y"] = GetRoundedFloat(rect.y);
				rectData["w"] = GetRoundedFloat(rect.width);
				rectData["h"] = GetRoundedFloat(rect.height);
				return rectData;
			} else if (inst is Vector2) {
				var vec2 = (Vector2)inst;
				JsonData vec2Data = new JsonData();
				vec2Data["x"] = GetRoundedFloat(vec2.x);
				vec2Data["y"] = GetRoundedFloat(vec2.y);
				return vec2Data;
			} else if (inst is Vector3) {
				var vec3 = (Vector3)inst;
				JsonData vec3Data = new JsonData();
				vec3Data["x"] = GetRoundedFloat(vec3.x);
				vec3Data["y"] = GetRoundedFloat(vec3.y);
				vec3Data["z"] = GetRoundedFloat(vec3.z);
				return vec3Data;
			} else if (inst is Vector4) {
				var vec4 = (Vector4)inst;
				JsonData vec4Data = new JsonData();
				vec4Data["x"] = GetRoundedFloat(vec4.x);
				vec4Data["y"] = GetRoundedFloat(vec4.y);
				vec4Data["z"] = GetRoundedFloat(vec4.z);
				vec4Data["w"] = GetRoundedFloat(vec4.w);
				return vec4Data;
			}else if(inst is Vector2Int){
                var vec2 = (Vector2Int)inst;
                JsonData vec2Data = new JsonData();
                vec2Data["x"] = vec2.x;
                vec2Data["y"] = vec2.y;
                return vec2Data;
            }
            else if (inst is Vector3Int){
                var vec3 = (Vector2Int)inst;
                JsonData vec3Data = new JsonData();
                vec3Data["x"] = vec3.x;
                vec3Data["y"] = vec3.y;
                return vec3Data;
            }
            else if (inst is GameObject) {
#if UNITY_EDITOR
                var path = AssetDatabase.GetAssetPath((GameObject)inst);
				return path;
#endif

            } else {
				JsonData data = new JsonData();
				Type type = inst.GetType();
				var classAttribute = Attribute.GetCustomAttribute(type, typeof(JsonClassAttribute), true) as JsonClassAttribute;
				if (classAttribute != null) {
					data[JsonAttribute.ReservedWordClass] = type.ToString();
				}

				var list = GetAttributeMembers<JsonAttribute>(inst);

				foreach (var member in list) {
					var attribute = GetAttributeByMember<JsonAttribute>(member);
					foreach (var word in JsonAttribute.ReservedWords) {
						if (attribute._key == word) {
							throw new Exception("In json attribute, we keep \"" + word + "\" as a preserved word, please choose another key.");
						}
					}

					SetJson(data, attribute._key, GetJsonData(GetValueOfMember(inst, member)));
				}
				return data;
			}
		}
	}
	#endif

	#endregion

	#region read from json to instance

	/// <summary>
	/// <para>缓存特性反射信息以提升编辑器运行效率</para>
	/// </summary>
	static Dictionary<MemberInfo, List<Attribute>> _attributeCache = new Dictionary<MemberInfo, List<Attribute>>();

	/// <summary>
	/// <para>通过成员信息获取Attribute（特性）</para>
	/// </summary>
	static T GetAttributeByMember<T>(MemberInfo member) where T : Attribute
	{
		if (member != null) {
			if (_attributeCache.ContainsKey(member)) {
				for (int i = 0; i < _attributeCache[member].Count; ++i) {
					if (_attributeCache[member][i] is T) {
						return (T)_attributeCache[member][i];
					}
				}
			}

			var objs = member.GetCustomAttributes(typeof(T), true);
			if (objs != null && objs.Length > 0) {
				T attr = (T)objs[0];
				if (!_attributeCache.ContainsKey(member))
					_attributeCache.Add(member, new List<Attribute>() { attr });
				else
					_attributeCache[member].Add(attr);
				return attr;
			}
		}

		return null;
	}

	/// <summary>
	/// <para>JsonData类型显式强制转换为float类型</para>
	/// </summary>
	public static float Json2Float(JsonData data)
	{
		return (float)(double)data;
	}

    /// <summary>
	/// <para>JsonData类型显式强制转换为float类型</para>
	/// </summary>
	public static int Json2Int(JsonData data)
    {
        return (int)data;
    }

    /// <summary>
    /// <para>将Json数据反序列化到一个对象</para>
    /// </summary>
    public static bool ReadFromJson(ref object inst, Type type, JsonData data, int fixedLength = 0)
	{
		var success = true;
		if (data == null) {
			inst = null;
		} else if (data.IsArray) {
			ReadFromJsonArray(ref inst, type, data, fixedLength);
		} else {
			// 数组或List将会兼容单个数据
			if (MiscUtils.HasInterface(type, typeof(IList))) {
				var jdArray = new JsonData();
				jdArray.Add(data);
				ReadFromJsonArray(ref inst, type, jdArray, fixedLength);
			} else {
				object val = null;
				if (data.IsBoolean) {
					val = (bool)data;
				} else if (data.IsDouble) {
					ReadFromDouble(ref val, type, data);
				} else if (data.IsInt) {
					val = (int)data;
				} else if (data.IsLong) {
					val = (long)data;
				} else if (data.IsString) {
					ReadFromString(ref val, type, (string)data);
				} else if (data.IsObject) {
					if (ReadFromJsonSpecialObject(ref val, type, data)) {
					} else if (MiscUtils.HasInterface(type, typeof(IDictionary))) {
						ReadFromJsonDictionary(ref val, type, data);
					} else {
						ReadFromJsonObject(ref val, type, data);
					}
				} else {
					Debug.LogWarning("Warning! Unsupported json type: " + data.GetJsonType().ToString());
					success = false;
				}
				inst = val;
			}
		}

		return success;
	}

	/// <summary>
	/// <para>从字符串读取各种类型数据</para>
	/// </summary>
	static void ReadFromString(ref object inst, Type type, string str)
	{
		if (type == typeof(Boolean))
			inst = bool.Parse(str);
		else if (type == typeof(Int32))
			inst = int.Parse(str);
		else if (type == typeof(Int64))
			inst = long.Parse(str);
		else if (type == typeof(Double))
			inst = double.Parse(str);
		else if (type == typeof(Single))
			inst = float.Parse(str);
		else if (type.IsEnum)
			inst = int.Parse(str);
#if UNITY_EDITOR
        else if (type == typeof(GameObject))

            inst = AssetDatabase.LoadAssetAtPath<GameObject>(str);
#endif
        else
			inst = str;
	}

	/// <summary>
	/// <para>读取特殊对象</para>
	/// </summary>
	static bool ReadFromJsonSpecialObject(ref object inst, Type type, JsonData data)
	{
		if (type == typeof(Rect)) {
			inst = new Rect(Json2Float(data["x"]), Json2Float(data["y"]), Json2Float(data["w"]), Json2Float(data["h"]));
			return true;
		} else if (type == typeof(Vector2)) {
			inst = new Vector2(Json2Float(data["x"]), Json2Float(data["y"]));
			return true;
		} else if (type == typeof(Vector3)) {
			inst = new Vector3(Json2Float(data["x"]), Json2Float(data["y"]), Json2Float(data["z"]));
			return true;
		} else if (type == typeof(Vector4)) {
			inst = new Vector4(Json2Float(data["x"]), Json2Float(data["y"]), Json2Float(data["z"]), Json2Float(data["w"]));
			return true;
        } else if (type == typeof(Vector2Int))
        {
            inst = new Vector2Int(Json2Int(data["x"]), Json2Int(data["y"]));
            return true;
        }else if (type == typeof(Vector3Int))
        {
            inst = new Vector3Int(Json2Int(data["x"]), Json2Int(data["y"]), Json2Int(data["z"]));
            return true;
        }
        return false;
	}

	/// <summary>
	/// <para>创建数组或List对象</para>
	/// </summary>
	static void ReadFromJsonArray(ref object inst, Type type, JsonData data, int fixedLength = 0)
	{
		var len = fixedLength > data.Count ? fixedLength : data.Count;
		inst = Activator.CreateInstance(type);
		Type eleType = null;
		if (inst is Array) { // Array
			eleType = type.GetElementType();
			type.InvokeMember("Set", BindingFlags.CreateInstance, null, inst, new object[] { len });
		} else { // List<?>
			eleType = type.GetGenericArguments()[0];
			type.GetMethod("Clear").Invoke(inst, new object[]{ });
		}
		for (int i = 0; i < len; ++i) {
			object ele = null;
			if (data.Count > i)
				ReadFromJson(ref ele, eleType, data[i]);
			else {
				ele = GetDefaultValue(eleType);
			}
			if (inst is Array) { // Array
				type.GetMethod("SetValue").Invoke(inst, new object[]{ ele, i });
			} else { // List<?>
				type.GetMethod("Add").Invoke(inst, new object[]{ ele });
			}
		}
	}

	/// <summary>
	/// <para>获取默认值</para>
	/// </summary>
	static object GetDefaultValue(Type type)
	{
		object defaultVal = null;
		if (type == typeof(string))
			defaultVal = "";
		else if (type == typeof(GameObject))
			defaultVal = null;
		else {
			defaultVal = Activator.CreateInstance(type);
		}
		return defaultVal;
	}

	/// <summary>
	/// <para>创建浮点数对象</para>
	/// </summary>
	static void ReadFromDouble(ref object inst, Type type, JsonData data)
	{
		if (type == typeof(Single))
			inst = Json2Float(data);
		else if (type == typeof(Double))
			inst = (double)data;
		else
			Debug.LogError("Error read double in ReadFromJsonData:" + data.ToJson());
	}

	/// <summary>
	/// <para>从Json数据中创建对应的Dictionary对象</para>
	/// </summary>
	static void ReadFromJsonDictionary(ref object inst, Type type, JsonData data)
	{
		inst = Activator.CreateInstance(type);
		type.GetMethod("Clear").Invoke(inst, new object[] { });
		var keyType = type.GetGenericArguments()[0];
		var valType = type.GetGenericArguments()[1];
		foreach (string k in data.Keys) {
			object keyVal = null;
			object valVal = null;
			JsonData jd = null;
			try {
				jd = JsonMapper.ToObject(k);
			} catch {
				jd = new JsonData(k);
			}
			ReadFromJson(ref keyVal, keyType, jd);
			ReadFromJson(ref valVal, valType, data[k]);
			type.GetMethod("Add", new Type[] { keyType, valType }).Invoke(inst, new object[] { keyVal, valVal });
		}
	}

	/// <summary>
	/// <para>从Json中将数据读取到对象中</para>
	/// </summary>
	static void ReadFromJsonObject(ref object inst, Type instType, JsonData data)
	{
		if (data.Keys.Contains(JsonAttribute.ReservedWordClass))
			instType = Type.GetType(data[JsonAttribute.ReservedWordClass].ToString());
		if (!instType.IsAbstract)
			inst = Activator.CreateInstance(instType);
		else {
			Debug.LogError("Error read json object in ReadFromJsonData:" + data.ToJson());
			return;
		}
		foreach (string key in data.Keys) {
			var subdata = data[key];
			var member = GetJsonAttributeMemberByKey(inst.GetType(), key);
			if (member == null) {
				continue;
			}
			var type = GetTypeOfMember(member);
			object val = null;
			var fixedLength = 0;
			if (MiscUtils.HasInterface(type, typeof(IList))) {
				var ja = GetAttributeByMember<JsonAttribute>(member);
				fixedLength = ja.GetSublabels(inst).Length;
			}
			ReadFromJson(ref val, type, subdata, fixedLength);
			SetValueOfMember(ref inst, member, val);
		}

		#if UNITY_EDITOR
		SetEditorValueOfMember(ref inst);
		#endif
	}

	#if UNITY_EDITOR
	/// <summary>
	/// <para>设置仅在编辑器中使用的变量</para>
	/// </summary>
	public static void SetEditorValueOfMember(ref object inst)
	{
		var list = GetAttributeMembers<JsonEditorAttribute>(inst);
		foreach (var member in list) {
			var attribute = GetAttributeByMember<JsonEditorAttribute>(member);
			var val = GetValueOfMember(inst, GetJsonAttributeMemberByKey(inst.GetType(), attribute._relativeKey));
			attribute._specialMember.SetEditorValue(ref inst, member, val);
		}
	}

	#endif

	#endregion

	#region for editor

	#if UNITY_EDITOR
	/// <summary>
	/// <para>对编辑器中显示的条目排序</para>
	/// </summary>
	static void SortMemberList(Type type, List<MemberInfo> members, ref List<MemberInfo> newMembers)
	{
		var lastMembers = new List<MemberInfo>(newMembers);
		List<MemberInfo> otherMembers = new List<MemberInfo>();
		Dictionary<MemberInfo, int> offsets = new Dictionary<MemberInfo, int>();
		int superMemberCount = 0;
		foreach (var member in members) {
            string parentValue;
			bool negative = false;
			var parentMember = GetParentMember(type, member, ref negative, out parentValue);
			if (parentMember == null) { // 无父属性的属性放在最前面
				// 父类属性在前, 本类属性在后
				if (member.DeclaringType == type)
					newMembers.Add(member);
				else
					newMembers.Insert(superMemberCount++, member);
			} else if (lastMembers.Contains(parentMember)) { // 将属性加到父属性后面
				var offset = 0;
				if (!offsets.ContainsKey(parentMember)) {
					offsets.Add(parentMember, ++offset);
				} else
					offset = ++offsets[parentMember];
				newMembers.Insert(newMembers.IndexOf(parentMember) + offset, member);
			} else
				otherMembers.Add(member);
		}

		if (otherMembers.Count > 0)
			SortMemberList(type, otherMembers, ref newMembers);
	}

	/// <summary>
	/// <para>显示在编辑器面板中</para>
	/// </summary>
	public static void DisplayInEditor(object inst, float standardWidth)
	{
		var oldAttributeMembers = GetAttributeMembers<JsonAttribute>(inst);
		List<MemberInfo> attributeMembers = new List<MemberInfo>();
		SortMemberList(inst.GetType(), oldAttributeMembers, ref attributeMembers);

		var editorAttributeMembers = GetAttributeMembers<JsonEditorAttribute>(inst);
		foreach (var member in attributeMembers) {
			var attribute = GetAttributeByMember<JsonAttribute>(member);
			var jeaMember = GetEditorAttributeMember(member, editorAttributeMembers);
			var jeaAttribute = GetAttributeByMember <JsonEditorAttribute>(jeaMember);
			
			string label = attribute._label;
			var val = GetValueOfMember(inst, member);
            var jeaType = GetTypeOfMember(jeaMember);
			var memberType = GetTypeOfMember(member);
            #region List
            if (val is IList) {
				Type eleType = null;
				if (inst is Array) { // Array
					eleType = memberType.GetElementType();
				} else { // List<?>
					eleType = memberType.GetGenericArguments()[0];
				}
				var list = (IList)val;
				var labels = attribute.GetSublabels(inst);
				EditorGUILayout.BeginHorizontal();
				GUILayout.Label(label, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
				if (labels == null || labels.Length == 0) {
					if (GUILayout.Button("+", GUILayout.Width(20))) {
						LengthenList(list, memberType, list.Count + 1);
						SetValueOfMember(ref inst, member, list);
						if (jeaMember != null) {
							var jeaVal = GetValueOfMember(inst, jeaMember);
							LengthenList((IList)jeaVal, jeaType, ((IList)jeaVal).Count + 1);
							SetValueOfMember(ref inst, jeaMember, jeaVal);
						}
						continue;
					}
				} else {
					FixListLength(list, memberType, labels.Length);
				}
				EditorGUILayout.EndHorizontal();
				EditorGUILayout.BeginVertical();
				for (int i = 0; i < list.Count; ++i) {
					EditorGUILayout.BeginHorizontal();
					var eleVal = list[i];
					var lbl = i.ToString() + (labels.Length > i ? "(" + labels[i] + ")" : "");

					if (jeaAttribute != null) {
						var jeaVal = GetValueOfMember(inst, jeaMember);
						jeaAttribute._specialMember.DisplayInEditor(inst, standardWidth, lbl, jeaVal, member, jeaMember, i);
					} else {
						bool success;
                        //if (!eleVal.GetType().IsValueType && eleVal.GetType().IsDefined(typeof(JsonClassAttribute), false))
                        //{
                        //    DisplayInEditor(eleVal, standardWidth);
                        //}else
                        //{
                            var basicModifiedVal = DisplayBasicInEditor(eleType, lbl, eleVal, standardWidth, out success);
                            if (success)
                            {
                                list[i] = basicModifiedVal;
                                SetValueOfMember(ref inst, member, list);
                            }
                            else
                            {
                                EditorGUILayout.EndHorizontal();
                                DisplayInEditor(eleVal, standardWidth);
                                EditorGUILayout.BeginHorizontal();
                        }
                        //}
					}

					if ((labels == null || labels.Length == 0) && GUILayout.Button("-", GUILayout.Width(20))) {
						RemoveFromList(list, memberType, i);
						if (jeaMember != null) {
							var jeaVal = GetValueOfMember(inst, jeaMember);
							RemoveFromList((IList)jeaVal, jeaType, i);
							SetValueOfMember(ref inst, jeaMember, jeaVal);
						}
						break;
					}
					EditorGUILayout.EndHorizontal();
				}
				EditorGUILayout.EndVertical();
                #endregion List
            }
            else {
				if (jeaAttribute != null) {
					var jeaVal = GetValueOfMember(inst, jeaMember);
					jeaAttribute._specialMember.DisplayInEditor(inst, standardWidth, label, jeaVal, member, jeaMember);
				} else {
                    bool success;
					var basicModifiedVal = DisplayBasicInEditor(memberType, label, val, standardWidth, out success);
					if (success) {
						SetValueOfMember(ref inst, member, basicModifiedVal);
					} else {
						DisplayInEditor(val, standardWidth);
					}
				}
			}
		}
	}

	/// <summary>
	/// <para>将一个IList扩展到长度newLength, newLength不大于原长度时直接返回</para>
	/// </summary>
	static void LengthenList(IList list, Type type, int newLength)
	{
		if (newLength <= list.Count)
			return;
		if (list is Array) { // Array
			type.InvokeMember("Set", BindingFlags.CreateInstance, null, list, new object[] { newLength });
		} else { // List<?>
			for (int i = list.Count; i < newLength; ++i) {
				object defaultVal = GetDefaultValue(type.GetGenericArguments()[0]);
				type.GetMethod("Add").Invoke(list, new object[]{ defaultVal });
			}
		}
	}

	/// <summary>
	/// <para>将一个IList固定在长度length</para>
	/// </summary>
	static void FixListLength(IList list, Type type, int length)
	{
		if (list is Array) { // Array
			if (length != list.Count)
				type.InvokeMember("Set", BindingFlags.CreateInstance, null, list, new object[] { length });
		} else { // List<?>
			if (length > list.Count) {
				for (int i = list.Count; i < length; ++i) {
					object defaultVal = GetDefaultValue(type.GetGenericArguments()[0]);
					type.GetMethod("Add").Invoke(list, new object[]{ defaultVal });
				}
			} else if (length < list.Count) {
				for (int i = length; i < list.Count; ++i) {
					type.GetMethod("RemoveAt").Invoke(list, new object[]{ length });
				}
			}
		}
	}

	/// <summary>
	/// <para>从一个IList删除序号为index的元素</para>
	/// </summary>
	static void RemoveFromList(IList list, Type type, int index)
	{
		if (index >= list.Count || index < 0)
			return;
		if (list is Array) { // Array
			for (int i = index + 1; i < list.Count; ++i) {
				list[i - 1] = list[i];
			}
			type.InvokeMember("Set", BindingFlags.CreateInstance, null, list, new object[] { list.Count - 1 });
		} else { //List<?>
			type.GetMethod("RemoveAt").Invoke(list, new object[] { index });
		}
	}

	/// <summary>
	/// <para>在编辑器中显示基础类型</para>
	/// </summary>
	static object DisplayBasicInEditor(Type type, string label, object val, float standardWidth, out bool success)
	{
		success = true;
		if (type == typeof(Int32)) {
			return EditorGUILayout.IntField(label, (int)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Int64)) {
			return EditorGUILayout.LongField(label, (long)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Boolean)) {
			return EditorGUILayout.Toggle(label, (bool)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(String)) {
			return EditorGUILayout.TextField(label, (string)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Single)) {
			return EditorGUILayout.FloatField(label, (float)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Double)) {
			return EditorGUILayout.DoubleField(label, (double)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type.IsEnum) {
			return EditorGUILayout.EnumPopup(label, (Enum)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Rect)) {
			return EditorGUILayout.RectField(label, (Rect)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Vector2)) {
			return EditorGUILayout.Vector2Field(label, (Vector2)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Vector3)) {
			return EditorGUILayout.Vector3Field(label, (Vector3)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(Vector4)) {
			return EditorGUILayout.Vector4Field(label, (Vector4)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		} else if (type == typeof(GameObject)) {
			return EditorGUILayout.ObjectField(label, (GameObject)val, typeof(GameObject), false, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
		}else if (type == typeof(Vector2Int)) { 
            return EditorGUILayout.Vector2IntField(label, (Vector2Int)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
        }else if (type == typeof(Vector3Int)) { 
            return EditorGUILayout.Vector3IntField(label, (Vector3Int)val, GUILayout.Width(standardWidth), GUILayout.ExpandWidth(true));
        }

        success = false;
		return null;
	}

	/// <summary>
	/// <para>获取编辑器特有成员（带有JsonEditorAttribute特性的成员）</para>
	/// </summary>
	static MemberInfo GetEditorAttributeMember(MemberInfo jsonAttributeMember, List<MemberInfo> jsonEditorAttributeList)
	{
		var jsonAttribute = GetAttributeByMember<JsonAttribute>(jsonAttributeMember);
		if (jsonAttribute != null) {
			foreach (var member in jsonEditorAttributeList) {
				var jsonEditorAttribute = GetAttributeByMember<JsonEditorAttribute>(member);
				if (jsonEditorAttribute._relativeKey == jsonAttribute._key) {
					return member;
				}
			}
		}

		return null;
	}

	/// <summary>
	/// <para>获取编辑器特有成员（带有JsonEditorAttribute特性的成员）</para>
	/// </summary>
	static MemberInfo GetEditorAttributeMember(MemberInfo jsonAttributeMember, object inst)
	{
		var jsonEditorAttributeList = GetAttributeMembers<JsonEditorAttribute>(inst);
		return GetEditorAttributeMember(jsonAttributeMember, jsonEditorAttributeList);
	}

	#endif

	#endregion

}
